#include "StdAfx.h"
#include "Node.h"
using namespace std;


int inte=4;
int ruch=5;
//Node::Node(string Name,int x,int y,int Colour)
Node::Node(string Name,int Colour)
{
    X=0;
	Y=0;
	colour=Colour;
	NodeName = Name;
	visible = true;
	Height=4;						//RemboL : to dodalem
	//TreeNode = new wezel(&Name);
	//to moje

	father=NULL;
	previous=NULL;
	next=NULL;
	last=NULL;
	first=NULL;
//	Childrens=0;
	focus=false;
	link=false;
	ostatnio=NULL;
	//koniec
}

Node::Node() {Width=1;Height=56;}
Node::~Node(void)
{
}
//od tad dopisalem

void Node::addChild(string Name,Node *n,bool zp)
{
	Node *tmp,*tmp2;
	n->father=this;
	if(last==NULL)
	{
		last=n;
		first=n;
		n->X=X+this->getWidth()+30; //RemboL : to zmienilem
		n->Y=Y;
	}
	else
	{
		tmp=this->last;
		this->last=n;
		n->previous=tmp;
		tmp->next=n;
		
		tmp2=tmp;
		while(tmp2!=NULL)
		{
			if(tmp2->Y>tmp->Y)
				tmp=tmp2;
			tmp2=tmp2->last;
		}
		
		n->X=X+this->getWidth()+30;	//RemboL: to tez
		n->Y=tmp->Y+Height+inte;
		
		if(zp)
		rozszerzanie(n);
/*		while(tmp!=NULL)
		{
			tmp->Y=tmp->Y-Hei-inte;
			tmp=tmp->previous;
		}
*/
	}
	focus=false;
	n->focus=true;

}

void Node::addBrother(string Name,Node *n,bool zp)
{
	Node *tmp,*tmp2;
	if(father!=NULL){
		n->father=father;
		n->next=next;
		n->previous=this;
		if(next==NULL){
			father->last=n;
		}
		else
		{
			next->previous=n;
		}
		next=n;
		tmp=this;
		tmp2=this;
		while(tmp2!=NULL)
		{
			if(tmp2->Y>tmp->Y)
				tmp=tmp2;
			tmp2=tmp2->last;
		}
		
		n->X=X;
		n->Y=tmp->Y+Height+inte;
		if(zp)
		rozszerzanie(n);
		focus=false;
		n->focus=true;
	}
	else
		this->addChild(Name,n);
}


Node* Node::inLeft()
{
	if(father!=NULL)
	{
		focus=false;
		father->focus=true;
		father->ostatnio=this;
		return father;
	}
	else return this;
}
Node* Node::inUp()
{
	if(previous!=NULL)
	{
		focus=false;
		previous->focus=true;
		return previous;
	}
	else return this;
}
Node* Node::inDown()
{
	if(next!=NULL)
	{
		focus=false;
		next->focus=true;
		return next;
	}
	else return this;
}
Node* Node::inRight()
{	
	if(!visible) return this;
	if(ostatnio==NULL)
	{
		if(first==NULL)
			return this;
		else
		{
			focus=false;
			if(first->next==NULL)
			{
				first->focus=true;
				return first;
			}
			else
			{
				Node *tmp = first;
				bool t=true;
				while((tmp->next!=NULL)&&t)
				{
					int a=(tmp->X-X)*(tmp->X-X)+(tmp->Y-Y)*(tmp->Y-Y);
					int b=(tmp->next->X-X)*(tmp->next->X-X)+(tmp->next->Y-Y)*(tmp->next->Y-Y);
					if(a<=b) t=false;
					tmp=tmp->next;
				}
				tmp=tmp->previous;
				tmp->focus=true;
				return tmp;
			}
		}
	}
	else
	{
		focus=false;
		ostatnio->focus=true;
		return ostatnio;
	}
}

void Node::rozszerzanie(Node *n,int typ) //0 - bez zmian, 1- w gore, 2 - w dol;
{
	Node *tmp;
	if(typ==0)
	{
		tmp=n->previous;
		while(tmp!=NULL)
		{
			rozszerzanie(tmp,1);
			tmp=tmp->previous;
		}
		tmp=n->next;
		while(tmp!=NULL)
		{
			rozszerzanie(tmp,2);
			tmp=tmp->next;
		}
		if(n->father!=NULL)
		{
			rozszerzanie(n->father,0);
		}
	}
	if (typ==1)
	{
		tmp=n->first;
		while(tmp!=NULL)
		{
			rozszerzanie(tmp,1);
			tmp=tmp->next;
		}
		n->Y=n->Y-Height-inte;
	}
	if(typ==2)
	{
		tmp=n->first;
		while(tmp!=NULL)
		{
			rozszerzanie(tmp,2);
			tmp=tmp->next;
		}
		n->Y=n->Y+Height+inte;
	}

}

void Node::uncheck()
{
	Node *tmp;
	if(father!=NULL)
	{
		tmp=father->first;
		while(tmp!=NULL)
		{
			hightlighted=false;
			tmp=tmp->next;
		}
	}
}
void Node::visibility()
{
//Pawel 13.03.07 od
	if(visible) this->setInvisible();
	else this->setVisible();;
// Pawel 13.03.07 do
}


//Pawel 13.03.07 od
Node* Node::remove()
{
	if(!father) return this;
	else 
	{
//28.03.07 od
		int minimum=this->min(),maksimum=this->max();
		int g=Y-minimum,d=maksimum-Y;
		if(g<0) g=0;
		if(d<0) d=0;
		if(next||previous)
		{
			zwezanie(0,g+Height+inte,d+Height+inte);
		}
		else 
			zwezanie(0,g,d);
//28.03.07 do
		Node *brat=this->previous;
		if(!brat)	father->first=this->next;
		else{
			brat->next=this->next;
			this->father->ostatnio=brat;
		}
		brat=this->next;
		if(!brat)	father->last=this->previous;
		else{
			brat->previous=this->previous;
			this->father->ostatnio=brat;
		}
//19.04.07 Pawel od
		if(next)
		{
			next->focus=true;
			return next;
		}
		if(previous)
		{
			previous->focus=true;
			return previous;
		}
		father->focus=true;
		return father;
//19.04.07 Pawel do
	}
}

//Bury 10.04.07 od
/*funkcja check - opis w Node.h
przy poszukiwaniu czy kliknelismy na noda przy pierwszym uruchomieniu nako n przekazywany
jest root pozniej wskazniki to korzeni poddrzew
x i y to wspolrzedne klikniecia 
sprawdzamy czy x i y lezy w prostokacie do ktorego umownie nalezy node
UWAGA: tutaj dziala ladnie przy tej czcionce!!! przy kazdym nodzie wspolrzedne Y wskazuja o 10
za malo tzn to pixeli powyzej lewego gornego rogu NAPISU czyli litery
byc moze jest to spowodowane rootem gdyz akurat u niego X i Y wskazuja dokladnie na lewy 
gorny rog progtokata czy ramki co go otacza, 
JEZELI WIEC BEDZIEMY PLANOWAC ROZNEJ WIELKOSCI CZCIONKI BEDZIE SIE TRZEBA NAD TYM ZASTANOWIC
podejrzewam rowniesz ze zmienic bardzo duzo w programie:/
KONIEC UWAGI:P*/
void Node::wzgledna(int x,int y)
{
	if(this->visible)
	{
		Node* tmp=first;
		while(tmp)
		{
			tmp->wzgledna(x,y);
			tmp->X=tmp->X-x;
			tmp->Y=tmp->Y-y;
			tmp=tmp->next;
		}
	}
}

void Node::bezwzgledna(int x,int y)
{
	if(this->visible)
	{
		Node* tmp=first;
		while(tmp)
		{
			tmp->bezwzgledna(x,y);
			tmp->X=tmp->X+x;
			tmp->Y=tmp->Y+y;
			tmp=tmp->next;
		}
	}
}

void Node::zwezanie(int typ,int gora,int dol)	//typ 0-bez zmian, 1 - w gore, -1 w dol;
{									//h>0 zwezanie h<0 rozszerzanie
	Node *tmp;
	if(typ==0)
		{
			tmp=this->previous;
			while(tmp)				
			{
				tmp->zwezanie(1,gora,dol);
				tmp=tmp->previous;
			}
			tmp=this->next;
			while(tmp)
			{
				tmp->zwezanie(-1,gora,dol);
				tmp=tmp->next;
			}
			if(father) father->zwezanie(0,gora,dol);
		}
	else
		{
			if(visible)
			{
				tmp=first;
				while(tmp)
				{
					tmp->zwezanie(typ,gora,dol);
					tmp=tmp->next;
				}
			}
			if(typ>0) Y=Y+gora;
			else Y=Y-dol;
		}
	
}

int Node::max()
{
	Node *tmp=this;
	int m=Y;
	while(tmp->last&&tmp->visible)
	{
		tmp=tmp->last;
		if(m<tmp->Y) m=tmp->Y;
	}
	return m;
}

int Node::min()
{
	Node *tmp=this;
	int m=Y;
	while(tmp->first&&tmp->visible)
	{
		tmp=tmp->first;
		if(m>tmp->Y) m=tmp->Y;
	}
	return m;
}
//28.03.2007 Pawel do

//29.03.2007 Pawel od






void Node::setVisible()
{
	if(!visible)
	{
		visible=true;
		bezwzgledna(X,Y);
		int minimum=this->min(), maksimum=this->max();
		int g=minimum-Y,d=Y-maksimum;
		if(g>0) g=0;
		if(d>0) g=0;
		zwezanie(0,g,d);
	}
}

void Node::setInvisible()
{
	if(visible)
	{
		int minimum=this->min(),maksimum=this->max();
		wzgledna(X,Y);
		visible=false;
		int g=Y-minimum,d=maksimum-Y;
		if(g<0) g=0;
		if(d<0) d=0;
		zwezanie(0,g,d);
	}
}

Node* Node::check(Node *n, int X, int Y)
{
	Node *tmp=n;
	Node *tmpReturn=NULL;
	int x=X;
	int y=Y;

	
	{
		if ((tmp->getX()<=x)&&((tmp->getX()+tmp->getWidth())>=x)&&((tmp->getY()+10)<=y)&&((tmp->getY()+/*tmp->getHeight()+*/20)>=y))
		//jezeli lezy w prostokacie
		{
			tmp->focus=true;
			return tmp;
		}
		else//jezeli nie to przeszukiwanie rekurencyjne
		{
			if(tmp->getVisible()){//jezeli jest widzialny
			tmp=n->first;
			
			while(tmp!=NULL)
				
			{
				tmpReturn=tmp->check(tmp, x, y);
				if (tmpReturn!=NULL) return tmpReturn; 
				tmp=tmp->next;
			}
			}
			return NULL;
		}
	}
}
//Bury 10.04.07 do
void Node::nodeUp()
{
	if(!father)return;
	if(!next&&!previous)return;
	
	Node *tmp;
	if(previous)
	{
		tmp=previous;
		tmp->setInvisible();
		this->setInvisible();
		previous=tmp->previous;
		if(previous)
		{
			previous->next=this;
		}
		tmp->next=next;
		if(next)
		{
			next->previous=tmp;
		}
		next=tmp;
		tmp->previous=this;
		if(!tmp->next)
		{
			father->last=tmp;	
		}
		if(!previous)
		{
			father->first=this;
		}
		int r;
		r=this->Y;
		this->Y=tmp->Y;
		tmp->Y=r;
		tmp->setVisible();
		this->setVisible();
	}
	else
	{
		Node *tmp2=next;
		tmp=this;
		while(tmp)
		{
			tmp->setInvisible();
			tmp=tmp->next;
		}
		tmp=father->last;
		tmp->next=this;
		previous=tmp;
		next->previous=NULL;
		father->first=next;
		next=NULL;
		father->last=this;
		tmp=tmp2;
		while(tmp->next)
		{
			int r=this->Y;
			this->Y=tmp->Y;
			tmp->Y=r;
			tmp=tmp->next;
		}
		while(tmp2)
		{
			tmp2->setVisible();
			tmp2=tmp2->next;
		}
	}
}

void Node::nodeDown()
{
	if(!father)return;
	if(!next&&!previous)return;
	
	Node *tmp;
	if(next)
	{
		tmp=next;
		tmp->setInvisible();
		this->setInvisible();
		next=tmp->next;
		if(next)
		{
			next->previous=this;
		}
		tmp->previous=previous;
		if(previous)
		{
			previous->next=tmp;
		}
		previous=tmp;
		tmp->next=this;
		if(!tmp->previous)
		{
			father->first=tmp;	
		}
		if(!previous)
		{
			father->last=this;
		}
		int r;
		r=this->Y;
		this->Y=tmp->Y;
		tmp->Y=r;
		tmp->setVisible();
		this->setVisible();
	}
	else
	{
		Node *tmp2=previous;
		tmp=this;
		while(tmp)
		{
			tmp->setInvisible();
			tmp=tmp->previous;
		}
		tmp=father->first;
		tmp->previous=this;
		next=tmp;
		previous->next=NULL;
		father->last=previous;
		previous=NULL;
		father->first=this;
		tmp=tmp2;
		while(tmp->previous)
		{
			int r=this->Y;
			this->Y=tmp->Y;
			tmp->Y=r;
			tmp=tmp->previous;
		}
		while(tmp2)
		{
			tmp2->setVisible();
			tmp2=tmp2->previous;
		}
	}
}

//19.04.07 Pawel od
void Node::nodeLeft()
{
	if(!father||!father->father) return;
	Node *tmp=father,*tmp2;
	this->setInvisible();
	tmp2=this->remove();
	tmp2->focus=false;
	this->father=NULL;
	tmp->addBrother("",this);
	this->setVisible();
}

//19.04.07 Pawel do


void Node::moveX(int x)
{
	this->wzgledna(X,Y);
	if(x!=0)
	{
		if(x>0)
		{
			X=X+x;
		}
		else
		{
			if(father)
			{
				int odleglosc=X-(father->X+father->getWidth());
				if(odleglosc<=20) ;			//20 minimalna odstep miedzy nodami w poziomie; mozna zastapic stala
				else
				{
					odleglosc=odleglosc-20;
					if(odleglosc+x<0) X=X-odleglosc;
					else X=X+x;
				}
			}
			else
				X=X+x;
		}
	}
	this->bezwzgledna(X,Y);
}

void Node::moveY(int y)
{
	this->wzgledna(X,Y);
	Y=Y-y;
	this->bezwzgledna(X,Y);
	if(y<0)
	{
		int maximum=max();
		int ponizej;
		Node* tmp=this;
		while (tmp&&!tmp->next)
		{
			tmp=tmp->father;
		}
		if(tmp)
		{
			tmp=tmp->next;
			ponizej=tmp->Y;
			while(tmp&&tmp->father->visible)
			{
				if(tmp->Y<ponizej) ponizej=tmp->Y;
				tmp=tmp->first;
			}
			if(ponizej-maximum<15)
				this->zwezanie(0,0,ponizej-15-maximum);
		}
	}
	if(y>0)
	{
		int minimum=min();
		int powyzej;
		Node* tmp=this;
		while(tmp&&!tmp->previous)
		{
			tmp=tmp->father;
		}
		if(tmp)
		{
			tmp=tmp->previous;
			powyzej=tmp->Y;
			while(tmp&&tmp->father->visible)
			{
				if(tmp->Y>powyzej) powyzej=tmp->Y;
				tmp=tmp->last;
			}
			if(minimum-powyzej<15)
				this->zwezanie(0,minimum-powyzej-15,0);
		}
	}
}

void Node::move(int x,int y)
{
	moveX(x);
	moveY(y);
}

void Node::changeNodeName(string newNodeName)
{
	int tmp=this->getWidth();
	this->wzgledna(X,Y);
	NodeName=newNodeName;
	this->bezwzgledna(X-tmp+getWidth(),Y);
}